import React, { useState, useRef, useEffect } from 'react';
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { DragControls } from 'three/addons/controls/DragControls.js';

const SphereWithAxes: React.FC = () => {
  const [rotation, setRotation] = useState({ x: 0, y: 0, z: 0 });
  const [position, setPosition] = useState({ x: 0, y: 0, z: 0 });
  const [showAxes, setShowAxes] = useState(false);
  const mountRef = useRef<HTMLDivElement>(null);
  const sceneRef = useRef<THREE.Scene | null>(null);
  const cameraRef = useRef<THREE.PerspectiveCamera | null>(null);
  const rendererRef = useRef<THREE.WebGLRenderer | null>(null);
  const sphereRef = useRef<THREE.Mesh | null>(null);
  const axesHelperRef = useRef<THREE.AxesHelper | null>(null);
  const dragControlsRef = useRef<DragControls | null>(null);
  const orbitControlsRef = useRef<OrbitControls | null>(null);
  const raycaster = new THREE.Raycaster();
  const mouse = new THREE.Vector2();
  const isDragging = useRef(false);
  const startRotation = useRef({ x: 0, y: 0, z: 0 });
  const startMouse = useRef({ x: 0, y: 0 });

  useEffect(() => {
    // 初始化场景
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0xf0f0f0);
    sceneRef.current = scene;

    // 初始化相机
    const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
    camera.position.z = 5;
    cameraRef.current = camera;

    // 初始化渲染器
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(400, 400);
    if (mountRef.current) {
      mountRef.current.appendChild(renderer.domElement);
    }
    rendererRef.current = renderer;

    // 添加光源
    const ambientLight = new THREE.AmbientLight(0x404040);
    scene.add(ambientLight);
    const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
    directionalLight.position.set(1, 1, 1);
    scene.add(directionalLight);

    // 创建球体
    const geometry = new THREE.SphereGeometry(1, 32, 32);
    const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
    const sphere = new THREE.Mesh(geometry, material);
    scene.add(sphere);
    sphereRef.current = sphere;

    // 初始化轨道控制器
    const orbitControls = new OrbitControls(camera, renderer.domElement);
    orbitControls.enabled = false;
    orbitControlsRef.current = orbitControls;

    // 初始化拖动控制器
    const dragControls = new DragControls([], camera, renderer.domElement);
    dragControlsRef.current = dragControls;

    // 渲染循环
    const animate = () => {
      requestAnimationFrame(animate);
      renderer.render(scene, camera);
    };
    animate();

    return () => {
      if (mountRef.current && renderer.domElement.parentNode) {
        mountRef.current.removeChild(renderer.domElement);
      }
    };
  }, []);

  useEffect(() => {
    if (showAxes && sceneRef.current && axesHelperRef.current === null) {
      // 创建坐标轴
      const axesHelper = new THREE.AxesHelper(5);
      sceneRef.current.add(axesHelper);
      axesHelperRef.current = axesHelper;

      // 创建可拖动的坐标轴对象
      const draggableObjects: THREE.Mesh[] = [];
      const axisGeometries = [
        new THREE.CylinderGeometry(0.05, 0.05, 5, 32),
        new THREE.CylinderGeometry(0.05, 0.05, 5, 32),
        new THREE.CylinderGeometry(0.05, 0.05, 5, 32)
      ];
      const axisMaterials = [
        new THREE.MeshBasicMaterial({ color: 0xff0000 }),
        new THREE.MeshBasicMaterial({ color: 0x00ff00 }),
        new THREE.MeshBasicMaterial({ color: 0x0000ff })
      ];
      const axisPositions = [
        new THREE.Vector3(2.5, 0, 0),
        new THREE.Vector3(0, 2.5, 0),
        new THREE.Vector3(0, 0, 2.5)
      ];
      const axisRotations = [
        new THREE.Euler(0, 0, Math.PI / 2),
        new THREE.Euler(0, Math.PI / 2, 0),
        new THREE.Euler(Math.PI / 2, 0, 0)
      ];

      axisGeometries.forEach((geo, index) => {
        const axis = new THREE.Mesh(geo, axisMaterials[index]);
        axis.position.copy(axisPositions[index]);
        axis.rotation.copy(axisRotations[index]);
        sceneRef.current?.add(axis);
        draggableObjects.push(axis);
      });

      if (dragControlsRef.current && cameraRef.current && rendererRef.current) {
        dragControlsRef.current.objects = draggableObjects;
        dragControlsRef.current.addEventListener('drag', (event: any) => {
          const axis = event.object as THREE.Mesh;
          if (Array.isArray(axis.material) ? (axis.material[0] as THREE.MeshBasicMaterial).color.r === 1 : (axis.material as THREE.MeshBasicMaterial).color.r === 1) { // X 轴
            setPosition(prev => ({ ...prev, x: prev.x + event.delta.x }));
            if (sphereRef.current) {
              sphereRef.current.position.x += event.delta.x;
            }
          } else if (Array.isArray(axis.material) ? (axis.material[0] as THREE.MeshBasicMaterial).color.g === 1 : (axis.material as THREE.MeshBasicMaterial).color.g === 1) { // Y 轴
            setPosition(prev => ({ ...prev, y: prev.y + event.delta.y }));
            if (sphereRef.current) {
              sphereRef.current.position.y += event.delta.y;
            }
          } else if (Array.isArray(axis.material) ? (axis.material[0] as THREE.MeshBasicMaterial).color.b === 1 : (axis.material as THREE.MeshBasicMaterial).color.b === 1) { // Z 轴
            setPosition(prev => ({ ...prev, z: prev.z + event.delta.z }));
            if (sphereRef.current) {
              sphereRef.current.position.z += event.delta.z;
            }
          }
        });
      }
    } else if (!showAxes && sceneRef.current && axesHelperRef.current) {
      sceneRef.current.remove(axesHelperRef.current);
      axesHelperRef.current = null;
      if (dragControlsRef.current) {
        dragControlsRef.current.objects = [];
      }
    }
  }, [showAxes]);

  const onMouseMove = (event: React.MouseEvent<HTMLDivElement>) => {
    if (!mountRef.current || !sphereRef.current || !cameraRef.current || !sceneRef.current) return;

    // 计算鼠标位置
    const rect = mountRef.current.getBoundingClientRect();
    mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
    mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

    // 检测鼠标是否在球体上
    raycaster.setFromCamera(mouse, cameraRef.current);
    const intersects = raycaster.intersectObjects([sphereRef.current]);
    setShowAxes(intersects.length > 0);

    // 球体旋转逻辑
    if (isDragging.current) {
      const deltaX = event.clientX - startMouse.current.x;
      const deltaY = event.clientY - startMouse.current.y;

      if (sphereRef.current) {
        sphereRef.current.rotation.x = startRotation.current.x + deltaY * 0.01;
        sphereRef.current.rotation.y = startRotation.current.y + deltaX * 0.01;
        setRotation({
          x: sphereRef.current.rotation.x,
          y: sphereRef.current.rotation.y,
          z: sphereRef.current.rotation.z
        });
      }
    }
  };

  const onMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {
    if (!mountRef.current || !sphereRef.current || !cameraRef.current || !sceneRef.current) return;

    // 计算鼠标位置
    const rect = mountRef.current.getBoundingClientRect();
    mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
    mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

    // 检测是否点击了球体
    raycaster.setFromCamera(mouse, cameraRef.current);
    const intersects = raycaster.intersectObjects([sphereRef.current]);
    if (intersects.length > 0) {
      isDragging.current = true;
      startMouse.current = { x: event.clientX, y: event.clientY };
      if (sphereRef.current) {
        startRotation.current = {
          x: sphereRef.current.rotation.x,
          y: sphereRef.current.rotation.y,
          z: sphereRef.current.rotation.z
        };
      }
    }
  };

  const onMouseUp = () => {
    isDragging.current = false;
  };

  return (
    <div
      ref={mountRef}
      onMouseMove={onMouseMove}
      onMouseDown={onMouseDown}
      onMouseUp={onMouseUp}
      style={{ width: '400px', height: '400px' }}
    >
      <div style={{ position: 'absolute', top: '10px', left: '10px', backgroundColor: 'white', padding: '10px' }}>
        <p>Rotation: X: {rotation.x.toFixed(2)}, Y: {rotation.y.toFixed(2)}, Z: {rotation.z.toFixed(2)}</p>
        <p>Position: X: {position.x.toFixed(2)}, Y: {position.y.toFixed(2)}, Z: {position.z.toFixed(2)}</p>
      </div>
    </div>
  );
};

export default SphereWithAxes;
